home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / alpha.arc / AX25.C < prev    next >
C/C++ Source or Header  |  1988-07-26  |  9KB  |  318 lines

  1. /* Low level AX.25 frame processing - address header */
  2.  
  3. #include <stdio.h>
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "iface.h"
  7. #include "timer.h"
  8. #include "arp.h"
  9. #include "slip.h"
  10. #include "ax25.h"
  11. #include "lapb.h"
  12. #include <ctype.h>
  13.  
  14. /* AX.25 broadcast address: "QST-0" in shifted ascii */
  15. struct ax25_addr ax25_bdcst = {
  16.     'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1,
  17.     ('0'<<1) | E,
  18. };
  19. char axbdcst[AXALEN];    /* Same thing, network format */
  20. struct ax25_addr mycall;
  21. int digipeat = 1;    /* Controls digipeating */
  22.  
  23. /* Send IP datagrams across an AX.25 link */
  24. int
  25. ax_send(bp,interface,gateway,precedence,delay,throughput,reliability)
  26. struct mbuf *bp;
  27. struct interface *interface;
  28. int32 gateway;
  29. char precedence;
  30. char delay;
  31. char throughput;
  32. char reliability;
  33. {
  34.     char *hw_addr,*res_arp();
  35.     struct ax25_cb *axp,*find_ax25(),*open_ax25();
  36.     struct ax25 addr;
  37.     struct ax25_addr destaddr;
  38.     struct mbuf *tbp;
  39.     extern int16 axwindow;
  40.     void ax_incom();
  41.     int16 size,bsize,seq;
  42.  
  43.     if((hw_addr = res_arp(interface,ARP_AX25,gateway,bp)) == NULLCHAR)
  44.         return 0;    /* Wait for address resolution */
  45.  
  46.     if(delay || (!reliability && (interface->flags == DATAGRAM_MODE))){
  47.         /* Use UI frame */
  48.         return (*interface->output)(interface,hw_addr,
  49.             interface->hwaddr,PID_FIRST|PID_LAST|PID_IP,bp);
  50.     }
  51.     /* Reliability is needed; use I-frames in AX.25 connection */
  52.     memcpy(destaddr.call,hw_addr,ALEN);
  53.     destaddr.ssid = hw_addr[ALEN];
  54.  
  55.     if((axp = find_ax25(&destaddr)) == NULLAX25 || axp->state != CONNECTED){
  56.         /* Open a new connection or reinitialize the old one */
  57.         atohax25(&addr,hw_addr,(struct ax25_addr *)interface->hwaddr);
  58.         axp = open_ax25(&addr,axwindow,ax_incom,NULLVFP,NULLVFP,interface,(char *)0);
  59.         if(axp == NULLAX25){
  60.             free_p(bp);
  61.             return -1;
  62.         }
  63.     }
  64.     /* If datagram is too big for one frame, send all but the last with
  65.      * the extension PID. Note: the copy to a new buf is necessary because
  66.      * AX.25 may continue retransmitting the frame after a local TCB has
  67.      * gone away, and using the buf directly would cause heap garbage to be
  68.      * transmitted. Besides, nobody would ever use AX.25 anywhere
  69.      * high performance is needed anyway...
  70.      */
  71.     bsize = len_mbuf(bp);
  72.     seq = 0;
  73.     while(bsize != 0){
  74.         size = min(bsize,axp->paclen);
  75.         /* Allocate buffer, allowing space for PID */
  76.         if((tbp = alloc_mbuf(size + 1)) == NULLBUF)
  77.             break;        /* out of memory! */
  78.         *tbp->data = PID_IP;
  79.         if(seq++ == 0)
  80.             *tbp->data |= PID_FIRST;     /* First in sequence */
  81.         if(size == bsize)
  82.             *tbp->data |= PID_LAST;        /* That's all of it */
  83.         /* else more to follow */
  84.  
  85.         tbp->cnt = 1;
  86.         tbp->cnt += pullup(&bp,tbp->data + 1,size);
  87.         send_ax25(axp,tbp);
  88.         bsize -= size;
  89.     }
  90.     free_p(bp);    /* Shouldn't be necessary */
  91.     return 0;
  92. }
  93. /* Add AX.25 link header and send packet.
  94.  * Note that the calling order here must match ec_output
  95.  * since ARP also uses it.
  96.  */
  97. int
  98. ax_output(interface,dest,source,pid,data)
  99. struct interface *interface;
  100. char *dest;        /* Destination AX.25 address (7 bytes, shifted) */
  101.             /* Also includes digipeater string */
  102. char *source;        /* Source AX.25 address (7 bytes, shifted) */
  103. char pid;        /* Protocol ID */
  104. struct mbuf *data;    /* Data field (follows PID) */
  105. {
  106.     struct mbuf *abp,*cbp,*htonax25();
  107.     struct ax25 addr;
  108.     
  109.     /* Allocate mbuf for control and PID fields, and fill in */
  110.     if((cbp = pushdown(data,2)) == NULLBUF){
  111.         free_p(data);
  112.         return -1;
  113.     }
  114.     cbp->data[0] = UI;
  115.     cbp->data[1] = pid;
  116.  
  117.     atohax25(&addr,dest,(struct ax25_addr *)source);
  118.     if((abp = htonax25(&addr,cbp)) == NULLBUF){
  119.         free_p(cbp);    /* Also frees data */
  120.         return -1;
  121.     }
  122.     /* This shouldn't be necessary because redirection has already been
  123.      * done at the IP router layer, but just to be safe...
  124.      */
  125.     if(interface->forw != NULLIF)
  126.         return (*interface->forw->raw)(interface->forw,abp);
  127.     else
  128.         return (*interface->raw)(interface,abp);
  129. }
  130. /* Process incoming AX.25 packets.
  131.  * After optional tracing, the address field is examined. If it is
  132.  * directed to us as a digipeater, repeat it.  If it is addressed to
  133.  * us or to QST-0, kick it upstairs depending on the protocol ID.
  134.  */
  135. int
  136. ax_recv(interface,bp)
  137. struct interface *interface;
  138. struct mbuf *bp;
  139. {
  140.     void arp_input();
  141.     int ip_route();
  142.     struct ax25_addr *ap;
  143.     struct mbuf *htonax25(),*hbp;
  144.     char multicast;
  145.     int nrnodes = 0;
  146.     char control;
  147.     struct ax25 hdr;
  148.     struct ax25_cb *axp,*find_ax25(),*cr_ax25();
  149.     struct ax25_addr ifcall;
  150.     extern struct ax25_addr nr_nodebc ;
  151.  
  152.     /* Use the address associated with this interface */
  153.     memcpy(ifcall.call,interface->hwaddr,ALEN);
  154.     ifcall.ssid = interface->hwaddr[ALEN];
  155.  
  156.     /* Pull header off packet and convert to host structure */
  157.     if(ntohax25(&hdr,&bp) < 0){
  158.         /* Something wrong with the header */
  159.         free_p(bp);
  160.         return;
  161.     }
  162.     /* Scan, looking for our call in the repeater fields, if any.
  163.      * Repeat appropriate packets.
  164.      */
  165.     for(ap = &hdr.digis[0]; ap < &hdr.digis[hdr.ndigis]; ap++){
  166.         if(ap->ssid & REPEATED)
  167.             continue;    /* Already repeated */
  168.         /* Check if packet is directed to us as a digipeater */
  169.         if(digipeat && addreq(ap,&ifcall)){
  170.             /* Yes, kick it back out */
  171.             ap->ssid |= REPEATED;
  172.             if((hbp = htonax25(&hdr,bp)) != NULLBUF){
  173.                 if(interface->forw != NULLIF)
  174.                     (*interface->forw->raw)(interface->forw,hbp);
  175.                 else
  176.                     (*interface->raw)(interface,hbp);
  177.                 bp = NULLBUF;
  178.             }
  179.         }
  180.         free_p(bp);    /* Dispose if not forwarded */
  181.         return;
  182.     }
  183.     /* Packet has passed all repeaters, now look at destination */
  184.     if(addreq(&hdr.dest,&ax25_bdcst)){
  185.         multicast = 1;    /* Broadcast packet */
  186.     } else if(addreq(&hdr.dest,&ifcall)){
  187.         multicast = 0;    /* Packet directed at us */
  188.     } else if(addreq(&hdr.dest,&nr_nodebc)){
  189.         nrnodes = 1 ;
  190.     } else {
  191.         /* Not for us */
  192.         free_p(bp);
  193.         return;
  194.     }
  195.     if(bp == NULLBUF){
  196.         /* Nothing left */
  197.         return;
  198.     }
  199.     /* Sneak a peek at the control field. This kludge is necessary because
  200.      * AX.25 lacks a proper protocol ID field between the address and LAPB
  201.      * sublayers; a control value of UI indicates that LAPB is to be
  202.      * bypassed.
  203.      */
  204.     control = *bp->data & ~PF;
  205.     if(uchar(control) == UI){
  206.         char pid;
  207.  
  208.         (void) pullchar(&bp);
  209.         if(pullup(&bp,&pid,1) != 1)
  210.             return;        /* No PID */
  211.         /* NET/ROM is very poorly layered. The meaning of the stuff
  212.          * following the PID of CF depends on what's in the AX.25 dest
  213.          * field.
  214.          */
  215.         if(nrnodes){
  216.             if(pid == (PID_NETROM | PID_FIRST | PID_LAST))
  217.                 nr_nodercv(interface,&hdr.source,bp) ;
  218.             else     /* regular UI packets to "nodes" aren't for us */
  219.                 free_p(bp) ;
  220.             return ;
  221.         }
  222.         /* Handle packets. Multi-frame messages are not allowed */
  223.         switch(pid & (PID_FIRST | PID_LAST | PID_PID)){
  224.         case (PID_IP | PID_FIRST | PID_LAST):
  225.             ip_route(bp,multicast);
  226.             break;
  227.         case (PID_ARP | PID_FIRST | PID_LAST):
  228.             arp_input(interface,bp);
  229.             break;
  230.         default:
  231.             free_p(bp);
  232.             break;
  233.         }
  234.         return;
  235.     }
  236.     /* Find the source address in hash table */
  237.     if((axp = find_ax25(&hdr.source)) == NULLAX25){
  238.         /* Create a new ax25 entry for this guy,
  239.          * insert into hash table keyed on his address,
  240.          * and initialize table entries
  241.          */
  242.         if((axp = cr_ax25(&hdr.source)) == NULLAX25){
  243.             free_p(bp);
  244.             return;
  245.         }
  246.         axp->interface = interface;
  247.         /* Swap source and destination, reverse digi string */
  248.         ASSIGN(axp->addr.dest,hdr.source);
  249.         ASSIGN(axp->addr.source,hdr.dest);
  250.         if(hdr.ndigis > 0){
  251.             int i,j;
  252.  
  253.             /* Construct reverse digipeater path */
  254.             for(i=hdr.ndigis-1,j=0;i >= 0;i--,j++){
  255.                 ASSIGN(axp->addr.digis[j],hdr.digis[i]);
  256.                 axp->addr.digis[j].ssid &= ~(E|REPEATED);
  257.             }
  258.             /* Scale timers to account for extra delay */
  259.             axp->t1.start *= hdr.ndigis+1;
  260.             axp->t2.start *= hdr.ndigis+1;
  261.             axp->t3.start *= hdr.ndigis+1;
  262.         }
  263.         axp->addr.ndigis = hdr.ndigis;
  264.     }
  265.     if(hdr.cmdrsp == UNKNOWN)
  266.         axp->proto = V1;    /* Old protocol in use */
  267.     else
  268.         axp->proto = V2;
  269.  
  270.     lapb_input(axp,hdr.cmdrsp,bp);
  271. }
  272. /* Initialize AX.25 entry in arp device table */
  273. /* General purpose AX.25 frame output */
  274. int
  275. sendframe(axp,cmdrsp,ctl,data)
  276. struct ax25_cb *axp;
  277. char cmdrsp;
  278. char ctl;
  279. struct mbuf *data;
  280. {
  281.     struct mbuf *hbp,*cbp,*htonax25();
  282.     int i;
  283.  
  284.     if(axp == NULLAX25 || axp->interface == NULLIF)
  285.         return -1;
  286.  
  287.     /* Add control field */
  288.     if((cbp = pushdown(data,1)) == NULLBUF){
  289.         free_p(data);
  290.         return -1;
  291.     }
  292.     cbp->data[0] = ctl;
  293.  
  294.     axp->addr.cmdrsp = cmdrsp;
  295.     /* Create address header */
  296.     if((hbp = htonax25(&axp->addr,cbp)) == NULLBUF){
  297.         free_p(cbp);
  298.         return -1;
  299.     }
  300.     /* The packet is all ready, now send it */
  301.     if(axp->interface->forw != NULLIF)
  302.         i = (*axp->interface->forw->raw)(axp->interface->forw,hbp);
  303.     else
  304.         i = (*axp->interface->raw)(axp->interface,hbp);
  305.  
  306.     return i;
  307. }
  308. axarp()
  309. {
  310.     int psax25(),setpath();
  311.  
  312.     memcpy(axbdcst,ax25_bdcst.call,ALEN);
  313.     axbdcst[ALEN] = ax25_bdcst.ssid;
  314.  
  315.     arp_init(ARP_AX25,AXALEN,PID_FIRST|PID_LAST|PID_IP,
  316.      PID_FIRST|PID_LAST|PID_ARP,axbdcst,psax25,setpath);
  317. }
  318.